<?php

declare(strict_types=1);
namespace App\Common\Helpers;

use App\Common\Constants\StorageModeConstants;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use Hyperf\Guzzle\CoroutineHandler;
use League\Flysystem\FilesystemException;
use Mine\Exception\NormalStatusException;
use Mine\Helper\Str;
use Mine\MineUpload;

class CommonUpload extends MineUpload
{
    /**
     * 存储模式 1 本地 2 阿里云
     * @var string
     */
    protected string $storageMode = StorageModeConstants::LOCAL;


    public function uploadWrite($contents,$path = null,$extension = 'png'): string
    {
        $this->filesystem = $this->factory->get($this->getMappingMode());

        $uploadPath = $this->getPath($path, $this->getStorageMode() != 1);
        $filename = $this->getNewName() . '.' . Str::lower($extension);

        try {
            $this->filesystem->write($uploadPath . '/' . $filename, $contents);
        } catch (FilesystemException $e) {
            throw new NormalStatusException((string) $e->getMessage(), 500);
        }
        return $this->assembleUrl($path, $filename);
    }

    public function uploadRemoteFile(string $url,string $filename,string $path = '')
    {
        $this->storageMode = StorageModeConstants::OSS;
        $client = new Client([
            'timeout' => 30,
            'handler' =>  new CoroutineHandler(),
        ]);

        $this->filesystem = $this->factory->get($this->getMappingMode());

        $uploadPath = $this->getPath($path, $this->getStorageMode() != 1);

        try {
            $contents = $client->get($url)->getBody()->getContents();
            $this->filesystem->write($uploadPath . '/' . $filename, $contents);
        } catch (FilesystemException|GuzzleException $e) {
            throw new NormalStatusException((string) $e->getMessage(), 500);
        }
        $url = $this->assembleUrl($path, $filename);
        return config('file.storage.oss.domain','').$url;
    }

    /**
     * 设置存储模式
     *
     * 该方法用于设置对象的存储模式。接受一个字符串参数来指定存储模式，并返回对象自身的引用。
     *
     * @param string $storageMode 存储模式，具体模式由实现决定。
     * @return self 返回对象自身的引用，允许链式调用。
     */
    public function setStorageMode(string $storageMode): self
    {
        $this->storageMode = $storageMode;
        $this->filesystem = $this->factory->get($this->getMappingMode());
        return $this;
    }

    /**
     * 获取存储模式
     *
     * 本函数无参数。
     *
     * @return string 返回当前的存储模式。
     */
    public function getStorageMode(): string
    {
        return $this->storageMode;
    }

}